package nostalgia.collection;

import nostalgia.UserConfiguration;
import nostalgia.SystemConfiguration;
import nostalgia.gui.IProgressRunnable;

import java.io.*;
import java.util.*;

import org.tritonus.share.sampled.file.TAudioFileFormat;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioSystem;

public class DirectoryCollectionReader implements IProgressRunnable {
    private static final String STORE = "dc";
    private Map<Object, DirectoryCollectionItem> collection = new HashMap<Object,DirectoryCollectionItem>();

    public Map<Object, DirectoryCollectionItem> getCollection() {
        return collection;
    }

    private void read() throws IOException {
        read(null);
    }

    private void read(IProgressCallback progressCallback) throws IOException {
        File root = new File(UserConfiguration.getInstsance().getLocalCollectionDirectory());
        Map<String, DirectoryCollectionItem> storedFiles = load();
        Map<String, DirectoryCollectionItem> collectionFiles = new HashMap<String, DirectoryCollectionItem>();
        read(root, storedFiles, collectionFiles, progressCallback);
        Iterator it = storedFiles.values().iterator();
        while(it.hasNext()) {
            collection.remove(it.next());
        }
        store(collectionFiles);
    }

    private void read(File f, Map<String, DirectoryCollectionItem> storedFiles, Map<String, DirectoryCollectionItem> collectionFiles, IProgressCallback progressCallback) {
        //System.out.println(f.getAbsolutePath());
        if(f.isDirectory()) {
            File[] files = f.listFiles();
            for(int i = 0; i < files.length; i++) {
                read(files[i], storedFiles, collectionFiles, progressCallback);
            }
        }
        else {
            DirectoryCollectionItem oldItem = storedFiles.get(f.getAbsolutePath());
            DirectoryCollectionItem item;
            if(oldItem == null) {
                item = new DirectoryCollectionItem();
                item.setFile(f.getAbsolutePath());
            }
            else {
                item = oldItem;
            }
            if(f.lastModified() > item.getLastUpdate()) {
                item.setLastUpdate(f.lastModified());
                try {
                    AudioFileFormat baseFileFormat = AudioSystem.getAudioFileFormat(f);
                    if(baseFileFormat instanceof TAudioFileFormat) {
                        Map properties = ((TAudioFileFormat)baseFileFormat).properties();
                        item.setArtist((String)properties.get("author"));
                        item.setTitle((String)properties.get("title"));
                        item.setDuration((Long)properties.get("duration") / 1000000);
                        if(oldItem != null) {
                            collection.remove(oldItem);
                        }
                        collection.put(item, item);
                    }
                }
                catch(Exception e) {}
            }
            storedFiles.remove(item.getFile());
            collectionFiles.put(item.getFile(), item);
            if(progressCallback != null) {
                progressCallback.updateStatus(collectionFiles.size() + " files scanned");
            }
        }
    }

    public void store(Map<String, DirectoryCollectionItem> files) throws IOException {
        Iterator<DirectoryCollectionItem> it = files.values().iterator();
        File file = new File(SystemConfiguration.getInstsance().getUserDataDirectory(), STORE);
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), "UTF8");
        while(it.hasNext()) {
            writer.write(it.next().toString());
            writer.write("\n");
        }
        writer.close();
    }

    public Map<String, DirectoryCollectionItem> load() throws IOException {
        Map<String, DirectoryCollectionItem> files = new HashMap<String, DirectoryCollectionItem>();
        File file = new File(SystemConfiguration.getInstsance().getUserDataDirectory(), STORE);
        if(file.exists()) {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF8"));
            String line;
            while((line = reader.readLine()) != null) {
                DirectoryCollectionItem item = DirectoryCollectionItem.parse(line);
                files.put(item.getFile(), item);
                if(item.isMedia()) {
                    collection.put(item, item);
                }
            }
        }
        return files;
    }

    public void start(IProgressCallback progresssCallback) {
        new ReaderThread(progresssCallback).start();
    }

    protected class ReaderThread extends Thread {
        IProgressCallback progresssCallback;

        protected ReaderThread(IProgressCallback progresssCallback) {
            this.progresssCallback = progresssCallback;
        }

        @Override
        public void run() {
            try {
                read(progresssCallback);
                progresssCallback.finished();
            }
            catch(Exception e) {
                progresssCallback.error(e.getMessage());
            }
        }
    }

    public static void main(String[] argv) throws Exception {
        DirectoryCollectionReader reader = new DirectoryCollectionReader();
        reader.read();
    }
}
